#pragma once
#include <iostream>
#include <functional>
#include <cstdint>
#include <string>
#include <pthread.h>
#include "Log.hpp"

namespace ThreadModule
{
    using namespace LogModule;
    //原子计数器，记录线程的名称
    std::uint32_t cnt = 0;

    using threadfunc_t = std::function<void()>;

    enum class ThreadStatus
    {
        THREAD_NEW,
        THREAD_RUNNING,
        THREAD_STOP
    };

    class Thread
    {
    private:
        void SetName()
        {
            _threadname = "thread-" + std::to_string(cnt++);
        }

        static void *run(void *arg)
        {
            Thread *self = static_cast<Thread*>(arg);
            pthread_setname_np(pthread_self(), self->_threadname.c_str());

            self->_threadstatus = ThreadStatus::THREAD_RUNNING;
            if(!self->_is_join)
            {
                pthread_detach(pthread_self());
            }
            self->_func();
            return nullptr;
        }
    public:
        Thread(threadfunc_t func)
        :_threadstatus(ThreadStatus::THREAD_NEW)
        ,_is_join(true)
        ,_func(func)
        {
            SetName();
        }

        void EnableDetach()
        {
            if(_threadstatus == ThreadStatus::THREAD_NEW)
                _is_join = false;
        }

        void EnableJoin()
        {
            if(_threadstatus == ThreadStatus::THREAD_NEW)
            {
                _is_join = true;
            }
        }

        bool Start()
        {
            if(_threadstatus == ThreadStatus::THREAD_RUNNING)
                return true;
            int n = ::pthread_create(&_pid, nullptr, run, this);
            if(n != 0)
                return false;
            return true;
        }

        bool Join()
        {
            if(_is_join)
            {
                LOG(LogLevel::DEBUG) << "正在等待线程: " << _threadname << "！";
                int n = pthread_join(_pid, nullptr);
                if(n != 0)
                    return false;
                return true;
            }
            return false;
        }
        std::string Name()
        {
            return _threadname;
        }

        ~Thread(){}
    private:
        pthread_t _pid; //线程pid
        
        std::string _threadname; //线程名字
        ThreadStatus _threadstatus; //线程状态

        bool _is_join; //是否可等待
        threadfunc_t _func; //回调方法
    };
}